package com.coderli.shurnim.stock.biz.data;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.coderli.shurnim.stock.model.StockRealTimeData;

/**
 * 通用股票价格获取类，用于处理名称、代码、拼音转换等基本逻辑
 * 
 * @author OneCoder
 * @date 2013年8月19日 下午10:36:27
 * @website http://www.coderli.com
 */
public abstract class CommonDataInput implements StockDataInput {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(CommonDataInput.class);
	protected static final String SHANG_HAI = "sh";
	protected static final String SHEN_ZHEN = "sz";
	protected HttpClient httpClient = new DefaultHttpClient();
	private static final String STOCK_REG_PATTERN = "^(((002|000|300|600)[\\d]{3})|60[\\d]{4})$";
	private static final String SH_REG_PATTERN = "^(((600)[\\d]{3})|60[\\d]{4})$";
	private Pattern stockPattern = Pattern.compile(STOCK_REG_PATTERN);
	private Pattern shPattern = Pattern.compile(SH_REG_PATTERN);

	/**
	 * 执行查询请求，返回Response对象<br>
	 * 获取后务必关闭流
	 * 
	 * @param code
	 * @param urlPrefix
	 * @return
	 */
	protected HttpResponse getResponse(String code, String urlPrefix) {
		// 校验股票代码是否合法
		if (!validStockCode(code)) {
			return null;
		}
		String fullCode = getFullCode(code);
		String fullURl = urlPrefix + fullCode;
		return execute(fullURl);
	}

	/**
	 * 执行查询请求，并返回response中的第一行信息。
	 * 
	 * @param code
	 * @param urlPrefix
	 * @return
	 */
	protected String getInfoStr(String code, String urlPrefix, Charset charset) {
		HttpResponse response = getResponse(code, urlPrefix);
		if (response == null) {
			return null;
		}
		InputStream is = null;
		String dataInfo = null;
		try {
			is = response.getEntity().getContent();
			BufferedReader br = new BufferedReader(new InputStreamReader(is,
					charset));
			dataInfo = br.readLine();
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return dataInfo;
	}

	/**
	 * 执行请求
	 * 
	 * @return
	 */
	private HttpResponse execute(String url) {
		HttpGet get = new HttpGet(url);
		try {
			HttpResponse response = httpClient.execute(get);
			int statusCode = response.getStatusLine().getStatusCode();
			if (!isSuccess(statusCode)) {
				LOGGER.warn(
						"Get stock data is not successfully. Status code: {}",
						statusCode);
				return null;
			}
			return response;
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/*
	 * 校验股票代码是否合法
	 */
	protected boolean validStockCode(String code) {
		if (code != null && stockPattern.matcher(code).matches()) {
			return true;
		}
		LOGGER.warn("Invalid stock code {}", code);
		return false;
	}

	/**
	 * 获取完成的股票代码<br>
	 * 一般情况是在股票代码前添加<b><i>sh</i></b>或<b><i>sz</i></b>前缀<br>
	 * 特殊情况自己可复写该方法
	 * 
	 * @param code
	 * @return
	 */
	protected String getFullCode(String code) {
		if (shPattern.matcher(code).matches()) {
			return SHANG_HAI + code;
		} else {
			return SHEN_ZHEN + code;
		}
	}

	/**
	 * 判断请求是否正常返回，即判断状态码是否为200（酌情考虑200-300范围内均可）
	 * 
	 * @param response
	 * @return
	 */
	protected boolean isSuccess(int statusCode) {
		return statusCode == 200;
	}

	@Override
	public abstract StockRealTimeData getData(String code);

	@Override
	public StockRealTimeData getDataByName(String name) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public StockRealTimeData getDataByPY(String py) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map<String, StockRealTimeData> getDataList(String... codeList) {
		// TODO Auto-generated method stub
		return null;
	}

}
